package ru.gosoplata.service.conn
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	import ru.gosoplata.model.TmpModel;
	import ru.gosoplata.service.LocalConectionService;
	/**
	 * ...
	 */
	public class BillAcceptor extends EventDispatcher
	{
		public static const LOCKED:String = 'locked';
		
		public static const GET_CONFIG_VERSION:String = 'GetConfigVersion';
		public static const CONFIG_VERSION:String = 'ConfigVersion';
		public static const GET_CONFIG:String = 'GetConfig';
		public static const CONFIG:String = 'Config';
		
		private var _commandsStack:CammandsStack = new CammandsStack();
		private var _waitForResponce:Command;
		
		private var _lc:LocalConectionService = new LocalConectionService();
		
		private var _resiveCounter:uint = 0;
		
		// TODO: время ожидания ответа? или починить проблему статус-фэлс! можно по таймауту вызывать exeSays с параметрами ошибки и их уже обрабатывать!
		private var _responseTimeOut:Timer = new Timer(10000, 1);
		private var _work:Boolean=false;
		private var _lock:Boolean=false;
		
		public function get work():Boolean 
		{
			return _work;
		}
		
		public function get lock():Boolean 
		{
			return _lock;
		}
		
		public function BillAcceptor() 
		{
			_lc.client = this;//TODO: (парсер?)
			_responseTimeOut.addEventListener(TimerEvent.TIMER_COMPLETE, onSendTimeoutError);
		}
		
		// запрос версии конфига
		public function checkChange(perations:String,callBack:Function):void 
		{
			var command:Command = new Command(); 
			command.message = "CheckChange" + "="+perations;
			command.responce = "Change";
			command.error = "0";
			//command.timeout = 10000;
			command.lock = true;
			command.callBack = callBack;
			//command.priority = 0;
			send(command);
		}
		
		// запрос версии конфига
		public function getConfVer(callBack:Function):void 
		{
			var command:Command = new Command(); 
			command.message = GET_CONFIG_VERSION + "=true";
			command.responce = CONFIG_VERSION;
			command.error = "0";
			//command.timeout = 10000;
			//command.lock = true;
			command.callBack = callBack;
			//command.priority = 100;
			send(command);
		}
		// запрос части конфига
		public function getConf(partNum:uint, callBack:Function):void 
		{	
			var command:Command = new Command(); 
			command.message = GET_CONFIG + "=" + partNum;
			command.responce = CONFIG;
			command.error = "";
			//command.timeout = 10000;
			//command.lock = true;
			command.callBack = callBack;
			//command.priority = 100;
			send(command);
		}
		//TODO: не используется
		//public function getPrintStatus():void 
		//{	
			//send("GetPrtStatus=true", "PrtStatus");
		//}
		// включение/выключение купюроприемника
		// такого быть не может - что ValOn придет false но Coints=10 (10 номинал монеты)
		public function validatorOn(callBack:Function):void 
		{	
			var command:Command = new Command(); 
			command.message = "Validator=on&AccNum=" + TmpModel.payment.accountId + "&PrvId=" + TmpModel.payment.provider.providerID + "&MaxCashLimit=" + TmpModel.MAX_SUM_TERM + TmpModel.payment.getExtraFieldsString();
			command.responce = "ValOn";
			command.error = "false";
			command.timeout = 60000;
			command.lock = true;
			command.callBack = callBack;
			//command.priority = 0;
			send(command);
		}
		public function validatorOff(callBack:Function):void 
		{	
			var command:Command = new Command(); 
			command.message = "Validator=off";
			command.responce = "ValOff";
			command.error = "true";
			command.timeout = 60000;
			command.lock = true;
			command.callBack = callBack;
			//command.priority = 0;
			send(command);
		}
		//
		public function createPay(callBack:Function):void 
		{	
			var command:Command = new Command(); 
			command.message = TmpModel.payment.getCreatPayString() + "&CreatePay=true";
			command.responce = "PaySuccess";
			command.error = "true";
			//command.timeout = 10000;
			command.lock = true;
			command.callBack = callBack;
			//command.priority = 0;
			send(command);
		}
		//
		public function checkDispence(callBack:Function=null):void 
		{	
			var command:Command = new Command(); 
			command.message = "CheckDispence=true";
			command.responce = "Dispence";
			command.error = "false";
			//command.timeout = 10000;
			command.lock = true;
			command.callBack = callBack;
			//command.priority = 0;
			send(command);
		}
		//
		public function startDispence(callBack:Function):void 
		{	
			var command:Command = new Command(); 
			command.message = "GoDispence=true";
			command.responce = "DispenceEnd";
			command.error = "true";
			command.timeout = 120000;
			command.lock = true;
			command.callBack = callBack;
			//command.priority = 0;
			send(command);
		}
		//
		public function printCheck(callBack:Function=null):void 
		{	
			var command:Command = new Command(); 
			command.message = "PrintCheck=true";
			command.responce = "PrintEnd";
			command.error = "true";
			command.timeout = 60000;
			command.lock = true;
			command.callBack = callBack;
			//command.priority = 0;
			send(command);
		}
		//
		public function writeLog(str:String):void 
		{
			var command:Command = new Command();
			command.message = "WriteLog=" + str;
			command.responce = "Answer";
			command.error = "ok";
			//command.timeout = 10000;
			//command.lock = false;
			//command.callBack = null;
			command.priority = 100;
			send(command);
		}
		//
		public function wcStatus(callBack:Function):void 
		{	
			var command:Command = new Command(); 
			command.message = "WcStatus=true";
			command.responce = "WcStatus";
			command.error = "193,2,2";
			//command.timeout = 10000;
			command.lock = true;
			command.callBack = callBack;
			//command.priority = 0;
			send(command);
		}
		//
		public function wcOpen(id:uint,callBack:Function=null):void 
		{	
			var command:Command = new Command(); 
			command.message = "WcOpen=" + id;
			command.responce = "WcStatus";
			command.error = "193,2,2";
			//command.timeout = 10000;
			command.lock = true;
			command.callBack = callBack;
			//command.priority = 0;
			send(command);
		}
		//
		public function wcInit():void 
		{	
			var command:Command = new Command(); 
			command.message = "WcInit=true";
			command.responce = "WcStatus";
			command.error = "193,2,2";
			//command.timeout = 10000;
			//command.lock = false;
			//command.callBack = null;
			//command.priority = 0;
			send(command);
		}
		//
		public function wcEnterMenu(id:String):void 
		{	
			var command:Command = new Command(); 
			command.message = "WcEnterMenu=" + id;
			command.responce = "Answer";
			command.error = "ok";
			//command.timeout = 10000;
			//command.lock = false;
			//command.callBack = null;
			//command.priority = 0;
			send(command);
		}
		//
		public function wcServicer(str:String):void 
		{	
			var command:Command = new Command(); 
			command.message = "WcServicer=" + str;
			command.responce = "Answer";
			command.error = "ok";
			//command.timeout = 10000;
			//command.lock = false;
			//command.callBack = null;
			//command.priority = 0;
			send(command);
		}
		
		//TODO: перенести в клиент (парсер?)
		//key=var&key=var
		public function exeSays(mess:String):void 
		{
			TmpModel.debugOutput.add("TermConnection exeSays " + mess);
			
			//_responseTimeOut.reset();
			//_responseTimeOut.start();
			
			var callBack:Function
			if (_waitForResponce)
			{
				var variables:Object = { };
				var ar:Array = mess.split('&');
				for each (var str:String in ar) 
				{
					var p:int = str.search('=');
					variables[str.substring(0,p)] = str.substring(p+1);
				}
			
				var key:String;
				for (key in variables) 
				{
					//TmpModel.debugOutput.add("BillAcceptor exeSays " + _resiveCounter + " key:" + key + "  wait:" + _waitForResponce.responce + " callBack:" + _waitForResponce.callBack);
					// если ждем Answer а пришло еще что... 
					if (key == _waitForResponce.responce || _waitForResponce.responce=="Answer") 
					{
						if (_waitForResponce.callBack!=null) 
						{
							callBack = _waitForResponce.callBack;
						}
						_waitForResponce = null;
						dispatchEvent(new Event(key));//TODO: а может ли сервис вещать события?
						break;
					}
				}
			}
			_resiveCounter++;
			
			TermParser.parseResponse(mess);
			
			if (callBack != null ) {
				TmpModel.debugOutput.add("BillAcceptor callBack.");
				callBack(variables);
			}
			
			sendToExe();
		}
		
		public function restart():void 
		{
			_waitForResponce = null;
			sendToExe();
		}
		
		public function closeConnection():void 
		{
			_lc.destroy();
		}
		//
		private function send(message:Command):void 
		{	
			//TmpModel.debugOutput.add("BillAcceptor push to send : " + _commandsStack.length+"/"+message.id+ " - " + message.message+" (wait "+message.responce+") callBack:"+message.callBack);
			
			if (!_work)
			{
				_work = true;
				//TmpModel.tmpGlobalController.eventDispatcherMap(LOCKED, true);
			}
			
			_commandsStack.push( message );
			sendToExe();
		}
		//
		private function sendToExe():void 
		{
			if (_waitForResponce) 
			{
				//TmpModel.debugOutput.add("BillAcceptor wait !!! ");
				return;
			}
			
			//_responseTimeOut.reset();
			if (_commandsStack.length)
			{
				var command:Command = _commandsStack.shift() as Command;
				
				//_responseTimeOut.delay = command.timeout;
				//_responseTimeOut.start();
				
				_waitForResponce = command;
				
				//if(command.message.indexOf("WriteLog=")==0)TmpModel.debugOutput.log(command.message);
				TmpModel.debugOutput.add("BillAcceptor sendToEXE "+command.id+" "+command.message+" (wait "+command.responce+") callBack:"+command.callBack);
				_lc.send(command.message);
			}else 
			{
				_work = false;
				TmpModel.tmpGlobalController.eventDispatcherMap("end_work");
			}
			
			_lock = _waitForResponce?_waitForResponce.lock:false;
			TmpModel.tmpGlobalController.eventDispatcherMap(LOCKED, _lock);
		}
		
		private function onSendTimeoutError(e:TimerEvent):void 
		{
			//TODO: и что делать если ехе не отвечает??? только попровать перезагрузиться
			TmpModel.debugOutput.add('------------- onSendTimeoutError -------------');
			//TODO: пишим в шару и при перезапуске отправляем!
		}
	}
}